<template>
  <div v-show="isShow" class="panel-mask">
    <div class="select-panel">
      <div class="select-head">
        <span class="cancel" @click="cancel">取消</span>
        {{ title }}
        <span class="define" @click="define">确定</span>
      </div>
      <div class="select-sections">
        <div
          v-for="(optionList, field) in optionsGroup"
          :id="'section-' + field"
          :key="field"
          :ref="'section-' + field"
          class="select-section"
          :style="{ width: 100 / fields.length + '%' }"
          @mousewheel.prevent="mousewheel($event, field)"
          @touchstart.prevent="touchstart($event)"
          @touchend.prevent="touchend($event, field)"
        >
          <div class="select-focus" />
          <div class="select-options">
            <div
              v-for="(opt, index) in optionList"
              :key="index"
              class="select-option"
              :class="currentIndexs[field] == index ? 'selected' : ''"
            >
              {{ opt[field] }}
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'SelectPanel',
  data() {
    return {
      title: '',
      options: {},
      optionsGroup: {},
      isShow: false,
      currentIndexs: {},
      touchY: 0,
      fields: []
    }
  },
  methods: {
    show(title, options, fields, values, callback) {
      this.title = title
      this.options = options
      this.fields = fields
      this.callback = callback
      this.isShow = true
      this.initial()
      this.reverseSelect(values)
    },
    initial() {
      this.optionsGroup[this.fields[0]] = this.options
      this.fields.map((field, index) => {
        if (index > 0) {
          this.$set(this.optionsGroup, field, this.optionsGroup[this.fields[index - 1]][0].group)
        }
        this.$set(this.currentIndexs, field, 0)
      })
    },
    hide() {
      this.isShow = false
      this.fields.forEach((field) => {
        document.getElementById('section-' + field).scrollTop = 0
      })
      this.currentIndexs = {}
      this.touchY = 0
      this.options = []
      this.fields = []
      this.optionsGroup = {}
    },
    mousewheel(event, field) {
      if (event.deltaY < 0) {
        this.select(true, field)
      } else {
        this.select(false, field)
      }
    },
    touchstart(event) {
      this.touchY = event.touches[0].pageY
    },
    touchend(event, field) {
      if (this.touchY !== 0) {
        if (this.touchY - event.changedTouches[0].pageY > 10) {
          this.select(true, field)
        } else if (this.touchY - event.changedTouches[0].pageY < -10) {
          this.select(false, field)
        }
      }

      this.touchY = 0
    },
    select(isDown, field) {
      if (isDown && this.currentIndexs[field] < this.optionsGroup[field].length - 1) {
        this.currentIndexs[field]++
      } else if (!isDown && this.currentIndexs[field] > 0) {
        this.currentIndexs[field]--
      }

      const eleHeight = document.getElementsByClassName('select-option')[0].clientHeight
      document.getElementById('section-' + field).scrollTop = this.currentIndexs[field] * eleHeight

      if (this.fields.indexOf(field) < this.fields.length) {
        const opt = this.options[this.currentIndexs[field]]
        const nextField = this.fields[this.fields.indexOf(field) + 1]
        if (nextField) {
          this.$set(this.optionsGroup, nextField, opt.group)
          this.$set(this.currentIndexs, nextField, 0)
        }
      }

      this.clearNext(field)
    },
    reverseSelect(values) {
      for (let i = 0; i < values.length; i++) {
        if (values[i]) {
          const field = this.fields[i]
          const index = this.optionsGroup[field].findIndex((op) => { return op[field] === values[i] })

          if (index >= 0) {
            this.currentIndexs[field] = index

            const opt = this.options[this.currentIndexs[field]]
            const nextField = this.fields[this.fields.indexOf(field) + 1]
            if (nextField) {
              this.$set(this.optionsGroup, nextField, opt.group)
            }

            setTimeout(() => {
              const eleHeight = document.getElementsByClassName('select-option')[0].clientHeight
              document.getElementById('section-' + field).scrollTop = index * eleHeight
            }, 10)
          }
        }
      }
    },
    clearNext(field) {
      const index = this.fields.indexOf(field)
      for (let i = index + 1; i < this.fields.length; i++) {
        document.getElementById('section-' + this.fields[i]).scrollTop = 0
      }
    },
    cancel() {
      this.hide()
    },
    define() {
      const values = []
      for (const field in this.currentIndexs) {
        values.push(this.optionsGroup[field][this.currentIndexs[field]][field])
      }
      const lastField = this.fields[this.fields.length - 1]
      this.callback(values, this.optionsGroup[lastField][this.currentIndexs[lastField]])
      this.hide()
    }
  }
}
</script>

<style lang="scss" scoped>
.panel-mask {
  width: 100%;
  height: 100%;
  background: rgba(51, 51, 52, 0.3);
  position: fixed;
  top: 0;
  left: 0;
  z-index: 99;

  .select-panel {
    position: absolute;
    width: 100%;
    height: 240px;
    bottom: 0;

    .select-head {
      height: 40px;
      line-height: 40px;
      border-radius: 10px 10px 0 0;
      background: #f1f4f9;
      text-align: center;
      font-size: 14px;
      color: #333333;
      font-weight: 600;
      padding: 0 15px;

      .cancel {
        float: left;
        font-weight: 400;
        color: #939ba4;
      }

      .define {
        color: #0b82ff;
        float: right;
        font-weight: 400;
      }
    }

    .select-sections {
      width: 100%;
      height: 200px;
      background: #fff;

      .select-section {
        float: left;
        overflow: auto;
        height: 200px;

        .select-options {
          padding: 85px 0;
          background: #fff;

          .select-option {
            height: 30px;
            line-height: 30px;
            text-align: center;
            font-size: 15px;
            color: #333333;
          }

          .select-option.selected {
            font-size: 16px;
          }
        }
        .select-focus::before {
          content: " ";
          position: absolute;
          top: 40px;
          height: 85px;
          width: 100%;
          border-bottom: 1px solid #e2e4e8;
          background-image: -webkit-linear-gradient(
            top,
            transparent 0,
            rgba(255, 255, 255, 0.6) 0%,
            rgba(255, 255, 255, 0.4) 50%,
            rgba(255, 255, 255, 0.2) 100%,
            transparent
          );
        }

        .select-focus::after {
          content: " ";
          position: absolute;
          bottom: 0;
          height: 85px;
          width: 100%;
          border-top: 1px solid #e2e4e8;
          background-image: -webkit-linear-gradient(
            top,
            transparent 0,
            rgba(255, 255, 255, 0.2) 0%,
            rgba(255, 255, 255, 0.4) 50%,
            rgba(255, 255, 255, 0.6) 100%,
            transparent
          );
        }
      }
    }
  }
}
</style>
